﻿using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
namespace ScFramework.Core
{

/// <summary>
/// 每个流程中的模块类
/// </summary>
    public class SubmoduleBase
    {

        public class ActionPair
        {
            public int order;
            public Action<object> act;
        }
        /// <summary>
        /// 事件类型->注册事件 的映射
        /// </summary>
        private Dictionary<Tuple<Type, int>, List<ActionPair>> _innerMessageQueue = new Dictionary<Tuple<Type, int>, List<ActionPair>>();
        private List<Tuple<Type, object, object>> _penddingMessage = new List<Tuple<Type, object, object>>();


        protected Main _main;




        /// <summary>
        /// 获取静态工具组件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        protected T GetSystemModule<T>() where T : SystemModule => _main.Get<T>();
        /// <summary>
        /// 所有模块列表
        /// </summary>
        private readonly List<ModulePair> _modules = new List<ModulePair>();


        public virtual void OnInit(object args)
        {
       
        }

        /// <summary>
        /// 初始化所有模块
        /// </summary>
        public void InitModules(Main m,List<string>moduleList=null,object args=null)
        {
            _main = m;
            Debug.Assert(_modules.Count == 0);
            if (moduleList != null)
            {
           //     try
          //      {
                    foreach(var x in moduleList)
                    {
                        
                      //  var module = Activator.CreateInstance(Type.GetType(x)) as LogicModuleBase;
                        Add(GetSystemModule<TypeManager>().CreatInstanceByShortName<LogicModuleBase>(x),enableImmediate:true);
                    }
                /*}catch(Exception e)
                {
                    Debug.LogError($"加载逻辑模块{this}时错误\n"+e);
                }*/
            }
            SetAttribute(this);



/*            foreach(var x in _modules)
            {
                if (x.Enabled)
                {
                    x.Module.OnEnable();
                }
            }*/

            OnInit(args);
            Debug.Assert(Enable);
            OnEnable();

            DisPatchPendingMsg();
        }


        /// <summary>
        /// 根据方法的特性设置其对事件的监听
        /// </summary>
        /// <param name="x"></param>
        private void SetAttribute(object x)
        {
            var methods = x.GetType().GetMethods(System.Reflection.BindingFlags.Public| System.Reflection.BindingFlags.NonPublic|System.Reflection.BindingFlags.Instance);
            foreach (var m in methods)
            {
                if (m.IsDefined(typeof(RegisterEvent), true))
                {
                    var tp = m.GetParameters();
                    if (tp.Length != 1)
                    {
                        Debug.LogError($"{m}:函数的参数不合法");
                        continue;
                    }
                    if (m.ReturnParameter.ParameterType != typeof(void))
                    {
                //        Debug.LogWarning($"{m}:函数的返回值不为空");
                     //   continue;
                    }
                    foreach (var a in m.GetCustomAttributes(true))
                    {
                        if (a.GetType() == typeof(RegisterEvent))
                        {
                            var aa = (a as RegisterEvent);
                            var id = new Tuple<Type, int>(aa.eventType, aa.eventID);
                            if (_innerMessageQueue.ContainsKey(id) == false)
                            {
                                _innerMessageQueue[id] = new List<ActionPair>();
                            }

                            _innerMessageQueue[id].Add(new ActionPair {
                                order=aa.order,
                                act=
                                (object args) => {
                                    if (args!=null&&tp[0].ParameterType.IsAssignableFrom(args.GetType()) == false)
                                    {
                               //         Debug.Log($"{m}的参数与发送的消息的参数类型{args.GetType()}不匹配");
                                        return;
                                    }else if (args == null&&tp[0].HasDefaultValue==false)
                                    {
                                //        Debug.Log($"{m}的参数与发送的消息的参数不匹配,发送消息参数不能为null");
                                        return;
                                    }


                                    m.Invoke(x, new object[] { args ==null?tp[0].DefaultValue:args});


                                }});
                        }
                    }
                }

            }
            foreach(var zzz in _innerMessageQueue)
            {
                zzz.Value.Sort((ActionPair a, ActionPair b) =>
                {
                    if (a.order == b.order) return 0;
                    else if (a.order < b.order) return -1;
                    else return 1;
                });
            }
        }

        public T GetInnerModule<T>()where T:IModuleInnerInterface{
            var type = typeof(T);

            var pair = _modules.Find((m) => (m.Module is T));
            if (pair == null)
            {
                Debug.Log("未注册的模块" + type.Name);

                return default(T);
            }
            if (pair.Enabled == false)
            {
                try
                {
                    pair.Module.OnEnable();
                    pair.Enabled = true;
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                }
            }
            return (T)(object)pair.Module;
        }

        public List<T> Gets<T>()
        {
            var type = typeof(T);
            if (type.IsInterface == false)
            {
                Debug.LogError("请使用接口获取组件");
                return null;
            }
            var pairs = _modules.FindAll((m) => (m.Module is T));
            foreach (var pair in pairs)
            {

                if (pair.Enabled == false)
                {
                    try
                    {
                        pair.Module.OnEnable();
                        pair.Enabled = true;
                    }
                    catch (Exception e)
                    {
                        Debug.LogError(e);
                    }
                }
            }
            return new List<ModulePair>(pairs).ConvertAll<T>(s => (T)(object)s.Module);
        }

        /// <summary>
        /// 获取子模块内逻辑模块的对应接口
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tag"></param>
        /// <returns></returns>
        public  T Get<T>()
        {            
            var type = typeof(T);
            /*if (type.IsInterface == false)
            {
                Debug.LogError("请使用接口获取组件");
                return default(T);
            }*/
            var pair = _modules.Find((m) => (m.Module is T));
            if (pair == null)
            {
                Debug.LogError("未注册的模块" + type.Name);

                return default(T);
            }
            if (pair.Enabled == false)
            {
                try
                {
                    pair.Module.OnEnable();
                    pair.Enabled = true;
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                }
            }
            return (T)(object)pair.Module;
        }

        
/// <summary>
/// 添加逻辑模块
/// </summary>
/// <param name="module"></param>
/// <param name="args"></param>
/// <param name="enableImmediate">添加时是否立即激活,为否则在第一次get此模块时激活;从表中加载的模块默认为true</param>
        
        protected void Add(LogicModuleBase module,object args=null,bool enableImmediate=false)
        {
            if (_modules.Find(s => s.ModuleType == module.GetType())!=null)
            {
                Debug.LogError($"{module}重复加载");
                return;
            }
            _modules.Add(new ModulePair(module.GetType(), module,enableImmediate));
            SetAttribute(module);


            module.Init(this,args);
        }
        protected void Dispatch<T>(T id, object args = null, bool blocking = true) where T : struct
        {
            Dispatch(typeof(T), id, args, blocking);
        }

        public void Dispatch(Type type,object id, object args = null,bool blocking=true)
        {
            if (Enable == false)
            {
                Debug.LogError("submodule is disabled when dispatch");
                return;
            }
            Debug.Assert(id.GetType() == type);
            if (blocking||onDispachPendingMsg)
            {
                if (_innerMessageQueue.ContainsKey(new Tuple<Type, int>(type,(int)id)) == false)
                {
            //        Debug.LogWarning($"{this}:在该模块中事件{id}未被注册");
                    return;
                }
                foreach(var m in _innerMessageQueue[new Tuple<Type, int>(type, (int)id)])
                {
                    m.act(args);
                }
            }
            else
            {
                if (args == null)
                {
                    _penddingMessage.UniqueAdd(new Tuple<Type, object, object>(type, id, args));
                }
                else
                {
                    _penddingMessage.Add(new Tuple<Type,object, object>(type,id, args));
                }
            }
        }

        public virtual void Update()
        {
            for (int i = 0; i < _modules.Count; i++)
            {
                var module = _modules[i];
         
                    module.Module.Update();
       
      
            }
        }

        bool onDispachPendingMsg = false;
        void DisPatchPendingMsg()
        {
            onDispachPendingMsg = true;
            var tp = new List<Tuple<Type,object, object>>(_penddingMessage.ToArray());
            _penddingMessage.Clear();
            foreach (var x in tp)
            {
                Dispatch(x.Item1, x.Item2,x.Item3);
            }
            onDispachPendingMsg = false;

        }
        public virtual void FixedUpdate()
        {


            for (int i = 0; i < _modules.Count; i++)
            {
                var module = _modules[i];
         //       try
                {
                    module.Module.FixedUpdate();
                }
           //     catch (Exception e)
                {
             //       Debug.LogError(e);
                }
            }

        }
        

        public virtual void LateFixedUpdate()
        {
            DisPatchPendingMsg();
            for (int i = 0; i < _modules.Count; i++)
            {
                var module = _modules[i];
                try
                {
                    module.Module.LateFixedUpdate();
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                }
            }



        }
        public bool Enable
        {
            get
            {
                return enable;

            }
            set
            {
                if (enable == value) return;
                else
                {
                    if (value)
                    {
                        enable = value;
                        OnEnable();
                    }
                    else
                    {
                        OnDisable();
                        enable = value;
                    }
                }

            }
        }
        private bool enable = true;
        public virtual void OnEnable() { 
            foreach(var x in _modules)
            {
                if (x.Enabled == true)
                {
                    x.Module.OnEnable();
                }
            }
        
        }
        public virtual void OnDisable() {
            DisPatchPendingMsg();
            foreach (var x in _modules)
            {
                if (x.Enabled == true)
                {
                    x.Module.OnDisable();
                }
            }
        } 

        public virtual void OnDestroy()
        {
            if (Enable)
            {
                Enable = false;
            }
            for (int i = 0; i < _modules.Count; i++)
            {
                var module = _modules[i];
                try
                {
                    module.Module.OnDestroy();
                    _main.DoRemove(module);
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                }
            }
            _main.DoRemove(this);
            GetSystemModule<MessageManager>().RemoveAbout(this);
            _modules.Clear();
            _innerMessageQueue.Clear();
            _penddingMessage.Clear();
        }

        private class ModulePair
        {
            public readonly Type ModuleType;
            public readonly LogicModuleBase Module;
            public bool Enabled;

            public ModulePair(Type moduleType, LogicModuleBase module,bool init)
            {
                ModuleType = moduleType;
                Module = module;
                Enabled = init;
            }
        }
    }
    /// <summary>
    /// 设置注册事件类型的监听
    /// </summary>
    [AttributeUsage(
    AttributeTargets.Method,
    AllowMultiple = true)]

    public sealed class RegisterEvent : Attribute
    {
        public int eventID;
        public Type eventType;
        public int order = 0;
        public RegisterEvent(object id)
        {
            //    Debug.Assert(id.GetType() == type);
            Debug.Assert(id.GetType().IsEnum);
            eventType = id.GetType();
            eventID = (int)id;
        }
    }
}
